التركيب


لترتيب اكثر للبيانات الموجودة في القوائم والهاشات ذلك يعرف بالتركيب

قائمة من قائمات(أو قائمة القوائم)

هي القائمة التي كل عنصر فيها قائمة عناصر ، تمثل القائمة من القائمة في الشكل بتركيب مشترك ويشار اليها في البيرل الى المصفوفة ذات البعدين




لايوفر البيرل المصفوفة ذات بعدين مباشرتاً لكنها تسمح بمحاكتها بإستخدام المصفوفة من مراجع مصفوفة array of array references


مرجع الى القائمة من القائمات

فمثلا ً اذا كان لدينا المصفوفة التالية

@table =(
( 1, 2, 3),
( 2, 4, 6),
( 3, 6, 9),
);

فهو لايتأثر بشىء وهي تكافئ كما لو كانت التالي

@table = (1,2,3,2,4,6,3,6,9);

دعنا نكتب مثال اخر بإستخدام المراجع

@row1 = ( 1, 2, 3);
@row2 = ( 2, 4, 6);
@row3 = ( 3, 6, 9);
@cols = (\@row1,\@row2,\@row3);
$table = \@cols;

يمكن ان يمثل



وللوصول الى هذة العناصر :

print "2 x 3 is ", $table , $table->[1]->[2];

يحتوي $table فقط عنوان بداية المصفوفة @cols ،والـ $table->[1] تعني عمل dereference لمرجع المصفوفة ( في المثال يشير الى المصفوفة @cols ) ثم الحصول على القيمة بالفهرس 1 ، واخيراً ->[2] تعني عمل dereference لـ $table->[1] ( في المثال row2) ثم الحصول على القيمة بالفهرس 2 ، يمكن ان يمثل هذا الوصول بما يلي:



وبنفس المثال مع مراجع الى المصفوفات مخفية :

$row1_ref = [ 1, 2, 3];
$row2_ref = [ 2, 4, 6];
$row3_ref = [ 3, 6, 9];
$table = [$row1_ref, $row2_ref, $row3_ref];

اصبح $table مرجع الى الصفوف والتي تشير الى القيم الاصلية ، الافضل حذف المتغيرات وضمها مع الاقواس المربعة

my $table =
[
[ 1, 2, 3],
[ 2, 4, 6],
[ 3, 6, 9],
];

فهذا المثال كما هو مشاهد اسفل بدون اسماء للمصفوفات ، ويمكن الوصول الى عناصرها باستخدام اما بواسطة عمل dereference للمرجع المصفوفة $table ، او بواسطة استعمال مؤثر dereference -> للوصول الى المصفوفة التحتية

print $table->[$x]->[$y];
print $table->[$x][$y]; # اوضح
print $$table[0][2];


وللوصول الى الصفوف

$second_row = $$table[1];
$second_row = $table->[1];

الان نفس العمل لإنشاء مصفوفة من مصفوفات

@list_of_lists=(
    [ "Mustang", "Bronco", "Ranger" ],
    [ "Cavalier", "Suburban", "Buick" ],
    [ "LeBaron", "Ram" ],
);

ولوصول الى تلك العناصر اما أستخدام المعامل -> او إزالتة

$list_of_lists[0][1];    # Bronco.  1st row, 2nd entry

$list_of_lists[1]->[2];    # Buick.  2nd row, 3rd entry

نلاحظ من السابق تم انشاء قائمة منتظمة @list_of_lists ، تحتوي هذة المصفوفة على ثلاثة مراجع الى القوائم الاخرى

print @list_of_lists;

فعند طباعتها يعرض على انها عناوين مصفوفة كالـ ARRAY(0x8060170) ... ...، وباستلام عنصر من قائمة @list_of_lists بإستخدام فهرس $list_of_lists[1] أي سوف تعيد المرجع في الصف الثاني للمصفوفة ، ولكي نتعامل مع العنصر في الصف يجب عمل لها dereference ، فاذا كانت مصفوفة يتم وضع الاشارة @ امام القائمة

$second_row = $list_of_lists[1];
@second_row =@{$list_of_lists[1]}; 

الفرق بين الاثنين ، المتغير $second_row هو مرجع الى الصف الثاني من مصفوفة ثنائية الابعاد ، سيحوي عنوان الصف الثاني عند التخصيص ، ولذلك اذا قمنا بعمل dereference للمتغير وقمنا بتعديل اي عنصر فأن التأثر سيكون على المصفوفة الاصلية

print $list_of_lists[1][1]; # prints 'Suburban'
$second_row ->[1] = "jreen";
print $list_of_lists[1][1]; # prints 'jreen'

بينما التخصيص الثاني نسخ لصف الثاني الى المصفوفة @second_row ،واي تعديل لان تتأثر به المصفوفة الاصلية .

لإيجاد عدد العناصر مصفوفتنا الخارجية outer ، نستخدم $# مع اسم المصفوفة ،وتضمين المصفوفة في scalar context

$#list_of_lists;         # Last element of @list_of_lists: 2

scalar(@list_of_lists);  # Number of rows in @list_of_lists: 3

ولإيجاد عدد العناصر من مصفوفة واحدة داخلية inner

scalar(@{$list_of_lists[2]});# Number of elements in the 3rd row

$#{$list_of_lists[1]};  # Index of last element in the 2nd row

ويمكن الاظافة الى المصفوفة

push(@list_of_lists,[ qw(Mercedes BMW Lexus) ]); # صف جديد
push(@{$list_of_lists[0]},qw(Taurus) );# اضافة عنصر الى الصف الاول


هاشات من هاشات

هو مشابة في انشاء قائمة من قوائم مع اختلاف بسيط في الصيغة

%hashes_of_hashes = (
1=> {
Name =>"John", Phone =>"123 4567890",Address=>"13 Acacia" },
2=> {
Name =>"Alan", Last=>"Smithee",Phone =>"not applicable"},
);

ونفس الشئ للوصول الى القيم

print $hashes_of_hashes{1}{Name},"\n";

وبختلاف بسيط لانشاء مرجع الى هاشات من هاشات وذلك بتغير % الى $ و علامات الحصر () الى {} ، وايضاً يمكن وضع الهاشات من هاشات متعددة :

%identities = (
JohnSmith => {
Name => { First=>"John", Last=>"Smith" },
Phone => { Home=>"123 4567890", Work=>undef },
Address => { Street => "13 Acacia Avenue",
City => "Arcadia City",
Country => "El Dorado",
}
},
AlanSmithee => {
Name => { First=>"Alan", Last=>"Smithee" },
Phone => { Work=>"not applicable" },
}
);

الهاش %identities لدية مفتاحين وهما JohnSmith و AlanSmithee وقيمهما هو مرجع الى الهاش المخفي وايضاً الهاش المخفي على سبيل المثال قيمة المفتاح Name هو ايضاً مرجع الى الهاش المخفي وللوصول الى هذا التركيب بشيء مماثل لما سبق عبر المرور على الهاشات

$first_name =$identities{'AlanSmithee'}{'Name'}{'First'};

تسمح البيرل بامتداد العناصر والفهارس (هاشات او مصفوفات)من خلال الهاش الفارغ او هاش موجود ويعرف sparse ،على سبيل المثال للإظافة مفتاح هاش جديد والقيمة بواسطة المرور من الهاشات المتعددة الى الوصول

$identities{JohnSmith}{Name}{YEM}="AMS";

وبنفس العمل السابق لوضع هاشات من هاشات متعددة

%identities = ( );

$identities{JohnSmith}{Name}{First}="John";
$identities{JohnSmith}{Name}{Last}="Smith";
%hash=%{$identities{JohnSmith}{Name}};
foreach (keys %hash)
{
print $_,"\t",$hash{$_},"\n";
}
my @array =(); # empty array
my %hash = (); # empty hash
my $arrayref=[]; # reference to empty array
my $hashref={}; # reference to empty hash


هناك انواع اخرى لتركيب البيانات :

الى غير ذلك من التركيب...فمن المصفوفات والمراجع تنشاء هذة Data Structures وحتي انها تصبح اكثر تعقيداً، وفي مايلي مثال لتركيبات اخرى ويمكنك فصل كل جزء وتجربة الوصول

#!/usr/bin/perl
# lists.pl
use warnings;
use strict;

my (@list_of_hashes, %hash_of_lists, %mixed_bag, $my_object);
my @my_list = (1,2,3,4,5);

@list_of_hashes = (
   { Monday=>1, Tuesday=>2, Wednesday=>3, Thursday=>4, Friday=>5 },
   { Red=>0xff0000, Green=>0x00ff00, Blue=>0x0000ff },
);
print "Tuesday is the $list_of_hashes[0]{Tuesday}nd day of the week.", "\n";

%hash_of_lists = (
    List_1 => [1, 2, 3],
    List_2 => ["Red", "Yellow", "Blue"],
);

print "The second element of List_1 is: $hash_of_lists{List_1}[1]", "\n";

%mixed_bag = (
    Scalar1 => 3,
    Scalar2 => "Hello World",
    List1 => [1, 2, 3],
    Hash1 => { A => 'Horses', C => 'Miles' },
    List2 => ['Hugh','Pugh', ['Barley-McGrew','Cuthbert'], 'Dibble', 'Grubb'],
    Scalar3 => $my_object,
    Hash2 => { Time => [ gmtime ],
               Date => scalar(gmtime), 
    },
    List3 => @my_list[0..2],
);

print $mixed_bag{List2}[2][1]; # produces 'Cuthbert'

في بداية البرنامج تم التصريح عن المتغيرات بإستخدام الدالة my ، ثم تعريف قائمة من هاشات المسمى @list_of_hashes ، و الوصول الى عناصرها باستعمال الصيغة المناسبة ،في هذة الحالة سوف تطبع قيمة 2 ، ثم تعريف هاش من قوائم المسمى %hash_of_lists والوصول اليها ، واخيراًُ تعريف مزيج بين الهاشات والقوائم من خلال الهاش %mixed_bag



المرور من خلال التركيب :

للمرور الى كل العناصر للتركيب البيانات ايضاً سهل كما رينا عند المرور من الهاشات والمصفوفات وايضاً التركيبات المعقدة سهل اذا كانت متجانسة و منظمة فعلى سبيل المثال للمرور من خلال القائمة من القائمات لطباعة العناصر

#!/usr/bin/perl
# simple1.pl
use warnings;
use strict;
my @outer = (['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']);
foreach my $outer_el (@outer) {
    foreach my $inner (@{$outer_el}) {
        print "$inner ";
    }
    print "\n";
}
يتم معرفة عدد الصفوف بطريقة اخرى (جافا) في المصفوفة من خلال array.length وتم معرفة عدد الاعمدة في كل صف من خلال الجملة array[i].length حيث i يمثل رقم الصف . for(i=0;i<array.length;i++) for(j=0;j<array[i].length;j++)

ولمرور من خلال الهاش من الهاشات

#!/usr/bin/perl
# simple2.pl
use warnings;
use strict;

my %outer = (A=> {a1=>1, a2=>2, a3=>3}, B=> {b1=>4, b2=>5, b3=>6},
             C=> {c1=>7,c2=>8, c3=>9});

foreach my $outer_key (keys %outer) {
    print "$outer_key => \n";
    foreach (keys %{$outer{$outer_key}} ) {
        print"\t$_ => $outer{$outer_key}{$_} \n";
    }
    print "\n";
}

وهنا ايضاً المرور من خلال قائمة من القوائمات وطباعة المشار والإمساك بالصفوف الغير معرفة

#!/usr/bin/perl
# simple3.pl
use warnings;
use strict;

my @outer;
@outer[1, 2, 5] = (['First', 'Row'], ['Second', 'Row'], ['Last', 'Row']);

for my $outer_elc (0..$#outer) {
    if ($outer [$outer_elc]) {
        my $inner_elcs = $#{ $outer[$outer_elc] };
        print "$outer_elc : ", $inner_elcs+1," elements \n";
        for my $inner_elc (0..$inner_elcs) {
            print "\t$inner_elc : $outer[$outer_elc][$inner_elc] \n";
        }
    } else {
        print "Row $outer_elc undefined\n";
    }
}

الاشياء تصبح اكثر تعقيداً عندما تكون مختلطة بين الانواع من البيانات ويمكن ان نلجئ الى الدالة ref والتالي دالة recursive (الدالة التي تستدعى نفسها )التي تطبع المتغيرات المتداخلة ( التي تتضمن كائنات ) وقوائم وهاشات الى اي مستوى من depth ، واستعمال الدالة ref لإيجاد ماهو العمل في كل مرحلة

#!/usr/bin/perl
# print_struct.pl
use warnings;
use strict;

my $mixed = [
    'scalar', ['a', 'list', ['of', 'many'], 'values'],
    {And=>{'A Hash'=>'Of Hashes'}}, \'plus a scalar ref'
];

print_structure($mixed);

sub print_structure {
    my ($data, $depth) = @_;

    $depth=0 unless defined $depth; #for initial call

    foreach (ref $data) {
        /^$/ and print($data,"\n"), next;
        /^SCALAR/ and print('-> ', $$data, "\n"), next;
        /^HASH/ and do {
            print "\n";
            foreach my $key (keys %{$data}) {
                print "\t" x$depth, "$key => ";
                print_structure ($data->{$key}, $depth+1);
            }
            next;
        };
        /^ARRAY/ and do {
            print "\n";
            for my $elc (0..$#{$data}) {
                print "\t" x$depth, "[$elc] : ";
                print_structure ($data->[$elc], $depth+1);
            }
            next;
        };
        # it is something else - an object, filehandle or typeglob
        print "?$data?";
    }
}


Typeglobs

هو نوع اخر من أنواع البيانات في البيرل فهو ملغم بجميع أنواع البيانات scalar, array, hash, filehandle في الحزمة نفسها، حيث يتكون من مرجع رئيسي وهذا المرجع ليس مرجع وحيد يشير لإي نوع من البيانات فهو بالاحراى له ستة شقوق slots التي يمكن ان تحتوي من ستة مراجع مختلفة في نفس الوقت وهم


scalar A reference to a scalar
array A reference to an array
hash A reference to a hash
code A code reference to a subroutine
handle A file or directory handle
format A format definition


الستة الشقوق في سلوك تعدد الاشكال polymorphic وهو الاسم الواحد للعديد من الاشكال ،يمكن ان يمثل كما في الشكل



ان برمجة Typeglobs شيء جيد ويستعمل لعدة اسباب ، في الايام القديمة (قبل وجود المراجع في البيرل ) كانت الـ typeglobs فقط طريقة لعبور الوسطاء الى الدالة بواسطة المرجع ( لذلك يمكن تخصيصة الية ) بدلاً من القيمة ،فهو يستعمل في اغلب الاوقات لعبور مقابض الملف filehandles من خلالة ،وقدرتة على امساك مقابض الملف اوالمجلد ، ومن دون هذا النوع سيكون صعباً معالجتة مع تركيب معقد

النوع الاخر للبيرل الذي لم نتطرق اليه حتى الان هو مقابض الملفات filehandles ، يمثل مقبض الملف قناة للدخل او الخرج التي ضمن البرنامج ، فعلى خلاف الأنواع السابقة فهو لا يقدمه اي رمز ،الشي المهم هو لكي ننشئ مقبض ملف نستخدم الدالة open

open FILEHANDLE, $filename;

في هذا المثال يفتح مقبض الملف FILEHANDLE للملف المحدد في المتغير filename الذي يحوي المسار الكامل ، ثم اجراء العمليات بعد فتحه مثل القراءة او الكتابة بواسطة <> او print على التوالي .

الوحدات البرمجية مثل IO::Handle, IO::File, IO::Dir لديها typeglobs كبيرة لتفصيل مقابض الملف بالمقابل عائلة وحــدات الخرج والدخل IO:: family لديها خارطة اضخم نسبياً ، بعض مبرمجين البيرل لايستخدمها الا في حالات خاصة ويمكن القول ان typeglobs مازالت تستخدم مع مقابض الملفات في البيرل .



تعريف Typeglobs

لتعريف هذا النوع يسبق بالعلامة * ولذا *name يحتوي القيم $name, @name, %name والقيم الاخرى لها ، سنحتاج فقط لإنشاءه الى قيمة تخصص اليه فمثلاً تخصيص typeglob من typeglob اخر :

*glob = *anotherglob;

فهذا التعبير يعمل نسخ لكل الستة الشقوق ( التي لاتلزم ان تكون جميعها معرفة ) المحتفظة في anotherglob الى glob ، وفي سلوك تعدد الاشكال يمكن تعريف العديد من الاشكال بنفس الاسم فعلى سبيل المثال

$message = "some text";
@message=(1,2,3,4,5);
*missive = *message; # تخصيص المصفوفة والمتغير
print $missive;   # produce "some text";

وبدلاً من ذلك يمكننا تخصيص مراجع وحد فقط

*glob = \$scalar;

فالتعبير السابق ينشاء typeglob جديد ويحتوي على مرجع المتغير scalar واعطى القيمة undef لخمس الشقوق الاخرى ، ويمكننا الوصول الى قيمة المتغير الجديد scalar بواسطة

print $glob;   # access typeglob scalar reference

ففي التعبيرين السابقين تخصيص المرجع scalar الى الـtypeglob وإنشاء متغير جديد المسمى $glob الذي يحتوي على نفس القيمة للمتغير الاصل $scalar ،هذا الشيء مفيد عندما يكون typeglob فيه العديد من الشقوق ونرغب في تعبة بعض الشقوق الى typeglob اخر والذي لان يتاثر على المعرف في التعبير

$message = "some text";
@message=(1,2,3,4,5);
*missive =\$message;
print ${*missive};
#print @{*missive};

في المثال عند تعبيه مرجع المصفوفة اليه فسوف يغادر الشق scalar

*glob = \$scalar;
*glob = \@array;

يملأ في شق المصفوفة وينشاء المتغير المسمى @glob التي تشير الى نفس قيم المصفوفة الاصل @array ، وبتغير المصفوفة الاصل( او المتغير $scalar ) سوف يغير @glob ( او المتغير $glob ) أوالعكس وهذا مايسمى بالـ aliasing الاسم المستعار، ويمكننا انشاء اسماء مستعاره لانواع الاخرى

*glob = \$scalar;   # create $glob as alias for $scala
*glob = \@array;    # create @glob as alias for @array
*glob = \%hash;     # create %glob as alias for %hash

واذا خصص الى اسم اخر

*glob2 = *glob;

فسوف ينسخ الثلاثة المراجع السابقة وإنشاء الاسم المستعارة $glob2, @glob2, %glob2 وكلا منهم يشرون الى نفس القيم الاصلية

ويمكننا تعريف مراجع code

*subglob = sub {return "An anonymous subroutine?"};	
or
*subglob = \&mysubroutine;

فكل تخصيص يمكن ان يستدعى من خلال subglob وبنفس الوصول ، فعلى سبيل المثال مرجع الدالة في السطر الثاني يمكن الوصول :

# متشابه
print mysubroutine(@args);
print subglob(@args);

لاحظ بهذة الطريقة يمكن عمل اسم للدالة المخفية:

#!/usr/bin/perl
# anonsub.pl
use warnings;
use strict;
my $anonsub = sub {print "Hello World"};
*namedsub = \&{$anonsub};
namedsub();


الوصول الى Typeglobs

على سبيل المثال اردت الوصول الى الهاش من خلال Typeglobs

# assign a new KEY to %glob
${*glob}{$KEY} = $value;

وبنفس العمل للوصول الى المتغير ${*glob} او المصفوفة @{*glob} او الدالة &{*glob} ، لانستطيع بانفس الصياغة مع مقابض الملف او التقارير(بوسطة الكلمة المحجوزة format )، فكلا النوعين لا تعرف بواسطة العلامة المسبقة في البداية كما في البقية ، وللوصول المباشر الى مختلف الشقوق فهي صيغة مشابة للوصول الى الهاش وكلاً منهم لدية مفتاح خاص ،العائد بواسطة الدالة ref لإعادة المرجع المحدد (او undef عندما الشق غير معرف)

$scalarref = *glob{SCALAR}; # same: $scalarref = \$glob
$arrayref = *glob{ARRAY};   # same: $arrayref = \@glob
$hashref = *glob{HASH};     # same: $hashref = \%glob 
$subref = *glob{CODE};      # same: $subref = \&glob
$fhref = *glob{IO}; # reference to IO handle named glob

ويمكن ان يكون المرجع عام الى الـtypeglob نفسة

$globref = *glob{GLOB};

ومن خلال NAME لمعرفة الاسم بدون ان يتقدم اي حزمة package

$globname = *glob{NAME}; # returns the string 'glob'

على العموم لانحتاجة في مراجع المتغيرات والدوال والهاش بسبب اننا نستطيع الوصول اليه مباشرتاً ، سنحتاجة فقط في مقابض الملف لفكه واستخراجه اوتوماتوكياً

print STDOUT "This goes to standard output";
print *STDOUT "The same thing, only indirectly";


مرجع رمزي الى typeglob

ان تخصيص typeglob الى شيء اخر ماعدا typeglob يسبب بتفسيره كامرجع ،ولنشاء ليظهر باسم typeglob مع الحزمة الحالية

$globname = *glob;
print $globname;   # produces '*main::glob'

فالسابق هو لنشاء symbolic reference to a typeglob، ولكي يمنع باستعمال use strict

*$globname = *anotherglob;   # aliases '*anotherglob' to '*glob'

على اي حال له استخدام واحد حيث يمكننا من الاشارة الى مقابض الملف عن طريق typeglobs


مرجع الى الـtypeglob

ولاخذ مرجع الى typeglob ويمكن الوصول اليه من خلال المرجع كاي مرجع بعمل deference

my $globref = \*glob;
$scalarref = $globref->{SCALAR};
#اقل وضوحاً او
${*$globref}  # لايسمح بازالة الاقواس بسبب “*$” متغير خاص 
%{*$globref}
&{*$globref}()

وبامكان تخزين اي مرجع سواء للمصفوفة او متغير او دالة اومرجع glob اخر

*parentglob = $globref;


المراجع الرمزية

هي طريقة اخر للوصول الى المتغيرات والدوال من خلال الـ symbol table ، فالمرجع الرمزي هو سلاسلة من الحروف تحتوي على اسم المتغير او اسم الدالة في جدول الترميز symbol table لحزمة معينة ، فعندما البيرل تقابلها اي من تلك السلسة الحرفية في اي مكان سوف تتوقع إيجادها كاي مرجع ، وسوف يبحث عنة في symbol table للحزمة الحالية واستبداله بالمرجع الى النوع الملائم ( متغير ، مصفوفة ، دالة ..الخ ) ، فلكل حزمة لها symbol table خاص بها وفيه اسماء تلك المتغيرات والدوال ... وبشكل اكثر المراجع الرمزية هو فقط عبارة عن نص ممثل في الكود بنفس اسم المتغير او الدالة او المصفوفة ... وبدقة يحون على الـ label التي تحمل في اسم typeglob ، والتي سوف تعاد للانجاز الوصول سواء كان الى المتغير او المصفوفة او الهاش اومقبض الملف او الدالة مع ذلك الاسم ، فعلى سبيل المثال المرجع الرمزي للمتغير @array هو النص “array”

#!/usr/bin/perl
# symbolic_ref.pl
use warnings;
use strict;
no strict 'refs'; # السماح للمراجع الرمزية
our @array = (1, 2, 3);   # only package variables allowed
my $symref = 'array';
my $total = $#$symref;
$total++;
print "$symref has $total elements \n";
foreach (@$symref) {
print "Got: $_ \n";
}

وبنفس عملية الإرجاع بواسطة عمل dereference للمرجع الرمزي من خلال @$arrayref ، فأي مرجع رمزي سوف يشير فقط الى متغير عام او بتعبير اخر المتغيرات الموجود في symbol table ، والمرجع نفسة يمكن ان يكون lexical فالمرجع لايتأثر بكونة lexical ، بينما لايمكن ان نشير الى المتغيرات التي تعلن مع my ، فهذا التحذير هام في حالة كون المرجع الرمزي غير محدد الحزمة فسوف يعتبر انة يشير الى اسم الحزمة الحالية ، بينما سوف يشير الى اسم الحزمة مع المرجع الرمزي من حزمة اخرى

my $symbolrefinotherpackage = 'My::Other::Package::variable';

فهذا الاستعمال يوضع بحذر مع الرمز :: خصوصاًُ مع المتغيرات الزائدة ، فالبيرل تترجم :: الى الاسم الصحيح فقط الذي يرجع ، ولمنع تاثير :: يتم تجاهلها بواسطة الرمز \ او بواسطة بناء اسم المتغير بطريقة اخرى فعلى سبيل المثال لمحاولة الى الوصول الى متغير الهاش %hash في الحزمة فالثلاثة الطرق صحيحة في التالي :

my $class="main";
my $value=${"$class::hash"}{value}; 
# ERROR - will dereference '$class::hash' within the string

# no longer looks like symbolic ref, OK
my $value=${"$class\:\:hash"}{value};
# concatenate strings, also OK
my $value=${$class."::hash"}{value};
# disambiguate with braces also OK but hard to read
my $value=${${class}::hash"}{value};

فالمرجع الرمزي لايتصف بأي نوع عند ارجاعة ، لذا يمكن ان نعمل dereference للمرجع بأي مرجع مطابق بتقديم الاشارة المناسبة

my $symref = "Package::variable";
my $scalar = $$symref;
my @array  = @$symref;
my %hash   = %$symref;
my $code   = &$symref;
my *glob   = *$symref;

فعلى سبيل المثال

#!/usr/bin/perl
use warnings;
use strict;
no strict 'refs'; 
package main;
our $name = "data1"; 
print ${"name"};# equivalent to: print $main::data
my $next="data2";
push @{$name}, $next;# equivalent to: push @main::data, $next
print join(' ',@{$name}),"\n";
#&{$name}();# equivalent to: &main::data()